package de.ret_world.openrpgstudio.editor.helpers;

import de.ret_world.openrpgstudio.editor.Project;
import java.io.BufferedReader;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import org.apache.log4j.Logger;
import org.luaj.vm2.LoadState;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaThread;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.LibFunction;
import org.luaj.vm2.lib.jse.JsePlatform;

/**
 * The ScriptTools class is a helper class for all your plugin library's script files. It has many methods to work with lua scripts (ex: run them).
 *
 * @author Emu
 */
public class ScriptTools {

    private ScriptTools() {
    }

    /**
     * @return the single instance of the class
     */
    public static ScriptTools getInstance() {
        return ScriptToolsHolder.INSTANCE;
    }

    private static class ScriptToolsHolder {

        private static final ScriptTools INSTANCE = new ScriptTools();
    }

    /**
     * Reads the given file into a String.
     * @param scriptFile the script file to be read
     * @return the script string
     */
    public String readScriptFile(Path scriptFile) {
        StringBuilder sb = new StringBuilder();

        try (BufferedReader in = Files.newBufferedReader(scriptFile, Charset.defaultCharset())) {
            String tmp = null;
            while ((tmp = in.readLine()) != null) {
                sb.append(tmp).append("\n");
            }
        } catch (IOException ex) {
            Logger.getLogger(ScriptTools.class).error(ex);
        }

        return sb.toString();
    }

    /**
     * Saves the given script string into the given lua file.
     * @param scriptFile the path to the script file
     * @param script the script string
     */
    public void saveScriptFile(Path scriptFile, String script) {
        try (FileWriter out = new FileWriter(scriptFile.toFile())) {
            out.write(script);
        } catch (IOException ex) {
            Logger.getLogger(ScriptTools.class).error(ex);
        }
    }

    /**
     * Executes the given script in the given Lua environment.
     * @param scriptID the ID of the script
     * @param env the environment in which the script should be executed
     */
    public void runScriptFile(String scriptID, LuaValue env) {
        try {
            Path p = Project.getInstance().getScriptRegister().getAbsolutePath(scriptID);

            LoadState.load(Files.newInputStream(p), p.getFileName().toString(), env).call();
        } catch (IOException ex) {
            Logger.getLogger(ScriptTools.class).error(ex);
        }
    }

    /**
     * Executes the given Lua script string in a given environment.
     * @param scriptString
     * @param env  
     */
    public void runScriptString(String scriptString, LuaValue env) {
        env.get("loadstring").call(LuaValue.valueOf(scriptString)).call();
    }

    public void executeStartScript() {
        Project.getInstance().getDatabase().clear();
        LuaTable env = JsePlatform.standardGlobals();
        LuaThread.setGlobals(env);
        for (LibFunction lib : Project.getInstance().getScriptRegister().getLibraries().values()) {
            env.load(lib);
        }

        ScriptTools.getInstance().runScriptFile("start", env);
    }
}
